Skip to content

feat(identity): 提供身份认证组件#2421

Merged
copytiao merged 26 commits intodevfrom
feat/IdentityModel
Feb 24, 2026
Merged

feat(identity): 提供身份认证组件#2421
copytiao merged 26 commits intodevfrom
feat/IdentityModel

Conversation

@copytiao
Copy link
Member

@copytiao copytiao commented Feb 15, 2026

本 PR 旨在提供规范的身份认证组件,以解决 PCL 内部的身份认证实现不规范还一堆 Bug 完全没有可维护性的问题

ToDo List

  • 实现 OAuth 认证(RFC 6749/RFC 8628)
  • 支持 OAuth 扩展实现(PKCE)
  • 支持 OpenId Connect(精简版)
  • 支持 Yggdrasil Connect
  • 支持传统 Yggdrasil

用例

Important

IdentityModel 不会尝试处理任何错误

因为其设计目标是作为协议传输层将调用方提供的数据转换为标准数据格式(类似 HttpClient)
错误需要调用方自行处理

普通 OAuth

初始化

var option = new OAuthClientOptions()
{
            ClientId = "0712",
            GetClient = () => _client,
            Headers = new(){
                ["User-Agent"] = "PCL-CE/2.14.2"
            },
            Meta = new EndpointMeta
            {
                AuthorizeEndpoint = "https://open.example.com/oauth/v2.0/authorize",
                DeviceEndpoint = "https://open.example.com/oauth/v2.0/device",
                TokenEndpoint = "https://open.example.com/oauth/v2.0/token"
            },
            RedirectUri = "http://localhost:7120/oauth/callback"
};

var client = new SimpleOAuthClient(option);

Tip

PKCE 扩展

如果需要 PKCE 扩展支持,请使用 PkceClient 而不是 SimpleOAuthClient

授权代码流

获取授权 Url

var authorizeUri = client.GetAuthorizeUrl(["offline_access"],"20120712");

使用授权代码兑换令牌

var result = await client.AuthorizeWithCodeAsync("",CancellationToken.None);

设备代码流

获取代码对

var data = await client.GetCodePairAsync(["offline_access"], CancellationToken.None);
var data = await client.AuthorizeWithDeviceAsync(data, CancellationToken.None);

Important

AuthorizeWithDeviceAsync 仅会发送一次请求(不会轮询)

你可以配合 Polly 做重试,或者自己糊也行,但绝对不能只调用一次

刷新登录

await client.AuthorizeWithSilentAsync(data, CancellationToken.None);

Tip

扩展数据支持

如果某一个协议基于 OAuth 但需要提供更多的请求载荷,你可以设置每个方法的 extData 参数(字典)并提供对应的数据

Warning

不要填写预定义字段

请不要试图填写诸如 client_id grant_type 之类的由 RFC 预先定义的字段,这些字段会被覆盖掉

如果实在有需要,请重新开一个类并实现 IOAuthClient 接口

OpenId Connect

Important

IdentityModel 提供的实现为精简版,可能不是标准 OpenID 实现,但应该够用.....吧?

初始化

Tip

设备代码流模式

如果只需要设备代码流登录,请设置 OnlyDeviceAuthorize 为 true,这将跳过 RedirectUri 的检查,从而允许传入空值

var options = new OpenIdOptions{
            OpenIdDiscoveryAddress = "https://openid.example.com/.well-known/openid-configuration",
            ClientId = "0712",
            GetClient = () => _client
};
var client = new OpenIdClient(options);

client.InitializeAsync(CancellationToken.None)

Important

因为需要从互联网拉取配置,基于 OpenID 协议(包括 OpenID)实现的客户端均需要在开始使用前调用 .InitializeAsync()

Tip

PKCE 支持

OpenID Client 原生支持(并默认启用) PKCE 扩展

如果 PKCE 扩展支持导致登录问题,请设置 EnablePkceSupport 为 false

OpenID Client 的登录过程与 OAuth 相同,请参考 SimpleOAuthClient 的用例

Yggdrasil Connect

Yggdrasil Connect Client 的初始化方式与 OpenID Client 相同,请直接参考 OpenID Client 的初始化方式

Yggdrasli Legacy Login

初始化

var options = new YggdrasilLegacyAuthenticateOptions
{
            Username = "LuoTianyi",
            Password = "QIDIJSIJIXIU*&*&*$&*$^*",
            AccessToken = "AccessToken",
            YggdrasilApiLocation = "https://api.example.com/yggdrasil",
            GetClient = () => _client
};
var client = new YggdrasilLegacyClient(options);
        

登录

var data = await client.AuthenticateAsync(CancellationToken.None);

刷新

var refreshData = await client.RefreshAsync(CancellationToken.None, new Profile
{
            Id = "LostInTianyi",
            Name = "LuoTianyi"
});

Important

如果需要选择档案,请务必在调用时传递要选择的档案

如果不需要,请移除传递

注销

await client.InvalidateAsync(CancellationToken.None);

全域登出

Important

此方法将登出全部账号,无论是不是 PCL CE 登录的

await client.SignOutAsync(CancellationToken.None);

@copytiao copytiao self-assigned this Feb 15, 2026
@pcl-ce-automation pcl-ce-automation bot added 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 size: L PR 大小评估:大型 labels Feb 15, 2026
@copytiao copytiao marked this pull request as draft February 15, 2026 11:18
@pcl-ce-automation pcl-ce-automation bot added 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中 and removed 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 labels Feb 15, 2026
@copytiao
Copy link
Member Author

大概做完了,实测下来感觉 Bug 不是很多,现在就差个 Yggdrasil 的传统认证组件了

@pcl-ce-automation pcl-ce-automation bot added size: XS PR 大小评估:微型 size: S PR 大小评估:小型 size: M PR 大小评估:中型 size: L PR 大小评估:大型 size: XL PR 大小评估:超大型 and removed size: L PR 大小评估:大型 size: XS PR 大小评估:微型 size: S PR 大小评估:小型 size: M PR 大小评估:中型 labels Feb 21, 2026
@pcl-ce-automation pcl-ce-automation bot added size: XXL PR 大小评估:巨型 and removed size: XL PR 大小评估:超大型 labels Feb 23, 2026
@copytiao copytiao marked this pull request as ready for review February 23, 2026 18:01
@pcl-ce-automation pcl-ce-automation bot added 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 and removed 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中 labels Feb 23, 2026
@copytiao copytiao requested a review from a team February 23, 2026 18:08
@copytiao
Copy link
Member Author

copytiao commented Feb 23, 2026

这堆东西完全没法做任何单元测试,只能等写账号系统的时候一并测掉了

目前手动测试下设备代码流是没什么问题了

Copy link
Contributor

@ruattd ruattd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不看了,炸了再说吧

记得把你的注释补上orz

Copy link
Contributor

@Pigeon0v0 Pigeon0v0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没看

@pcl-ce-automation pcl-ce-automation bot added 🕑 等待合并 已处理完毕,正在等待代码合并入主分支 and removed 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 labels Feb 24, 2026
@copytiao copytiao merged commit 4d9754f into dev Feb 24, 2026
2 checks passed
@pcl-ce-automation pcl-ce-automation bot added 👌 完成 相关问题已修复或功能已实现,计划在下次版本更新时正式上线 and removed 🕑 等待合并 已处理完毕,正在等待代码合并入主分支 labels Feb 24, 2026
@copytiao copytiao deleted the feat/IdentityModel branch February 24, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XXL PR 大小评估:巨型 👌 完成 相关问题已修复或功能已实现,计划在下次版本更新时正式上线

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants